package ru.ifmo.croak.impl.stress.query.team1;

import java.util.Collections;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Roman Kolganov
 * 26.05.11
 */
public class RandomAccessConcurrentSet<T> {
    private static final int THRESHOLD = 10;
    private static final int STEP = 10;
    private static final int DEFAULT_CAPACITY = (int) 1e7;
    private final int capacity;
    private final Set<T> set =
            Collections.newSetFromMap(new ConcurrentHashMap<T, Boolean>());
    private volatile T[] cache = (T[]) set.toArray();

    public RandomAccessConcurrentSet(int capacity) {
        this.capacity = capacity;
    }

    public RandomAccessConcurrentSet() {
        this(DEFAULT_CAPACITY);
    }

    public T randomElement(Random rand) {
        if (cache.length == 0) {
            return null;
        } else {
            return cache[SafeRandom.nextInt(rand, cache.length)];
        }
    }

    public T randomElement() {
        return randomElement(null);
    }

    public boolean add(T e, Random rand) {
        boolean result = set.add(e);
        if (cache.length < capacity && result &&
                (cache.length < THRESHOLD ||
                        SafeRandom.nextBoolean(rand, STEP))) {
            cache = set.toArray(cache);
        }
        return result;
    }

    public void add(T e) {
        add(e, null);
    }

}
